//
//  ZMCrashManager.m
//  ZMKitDemo
//
//  Created by zm on 2018/6/21.
//  Copyright © 2018年 zm. All rights reserved.
//

#import "ZMCrashManager.h"
#import <objc/runtime.h>

@implementation ZMCrashManager

+(instancetype)shared {
    static ZMCrashManager *manager = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        manager = [[self alloc] init];
    });
    return manager;
}

-(instancetype)init {
    if (self = [super init]) {
        [self fixWKContentViewCrash];
    }
    return self;
}


#pragma mark -

- (void)startMonitor {
#if !DEBUG
    //检测是否有crash发生，如果有crash发生，清除本地缓存
    [self checkLastCrash];
    //开始监测crash
    NSSetUncaughtExceptionHandler(&ZMUncaughtExceptionHandler);
#endif
}

-(void)checkLastCrash {
    if (![[NSUserDefaults standardUserDefaults] boolForKey:@"com.zmkit.crash.key"]) {
        // 程序没有发生crash
        return;
    }
    // 清空 NSUserDefaults
    NSUserDefaults *defs = [NSUserDefaults standardUserDefaults];
    [defs removePersistentDomainForName:[[NSBundle mainBundle] bundleIdentifier]];
    [defs synchronize];
    // 清空 caches和documents
    NSURL *cachesURL = [NSFileManager cachesURL];
    [[NSFileManager defaultManager] removeItemAtURL:cachesURL error:nil];
    NSURL *documentsURL = [NSFileManager documentsURL];
    [[NSFileManager defaultManager] removeItemAtURL:documentsURL error:nil];
}

static void ZMUncaughtExceptionHandler(NSException *exception) {
    if (exception == nil) return;
    
    if (ZMCrashManager.shared.crashHandler) {
        ZMCrashManager.shared.crashHandler(exception);
    }
    [[NSUserDefaults standardUserDefaults] setBool:true forKey:@"com.zmkit.crash.key"];
    [[NSUserDefaults standardUserDefaults] synchronize];
    
}

#pragma mark - 处理WKContentView的crash
/**
 处理WKContentView的crash
 [WKContentView isSecureTextEntry]: unrecognized selector sent to instance 0x101bd5000
 */
- (void)fixWKContentViewCrash {
    if (([[[UIDevice currentDevice] systemVersion] doubleValue] >= 8.0)) {
        const char *className = @"WKContentView".UTF8String;
        Class WKContentViewClass = objc_getClass(className);
        SEL isSecureTextEntry = NSSelectorFromString(@"isSecureTextEntry");
        SEL secureTextEntry = NSSelectorFromString(@"secureTextEntry");
        BOOL addIsSecureTextEntry = class_addMethod(WKContentViewClass, isSecureTextEntry, (IMP)isSecureTextEntryIMP, "B@:");
        BOOL addSecureTextEntry = class_addMethod(WKContentViewClass, secureTextEntry, (IMP)secureTextEntryIMP, "B@:");
        if (!addIsSecureTextEntry || !addSecureTextEntry) {
            NSLog(@"WKContentView-Crash->修复失败");
        }
    }
}

/**
 实现WKContentView对象isSecureTextEntry方法
 @return NO
 */
BOOL isSecureTextEntryIMP(id sender, SEL cmd) {
    return NO;
}

/**
 实现WKContentView对象secureTextEntry方法
 @return NO
 */
BOOL secureTextEntryIMP(id sender, SEL cmd) {
    return NO;
}


@end
